<?php

namespace common\core\server;

use common\core\base\InvalidException;
use common\helpers\BaseHelper;
use lengbin\helper\number\NumberHelper;
use server\trigger\OperationTrigger;
use yii\base\Component;
use yii\base\Event;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\helpers\HtmlPurifier;

class BaseServer extends Component
{

    use InvalidException;

    const EVENT_LOG_OPERATION = 'event.log.operation';

    public function behaviors()
    {
        // base trigger
        $baseTriggers = [
            OperationTrigger::class,
        ];
        foreach ($baseTriggers as $baseTrigger) {
            $trigger = \Yii::createObject($baseTrigger);
            $name = call_user_func([$trigger, 'name']);
            $this->on($name, [$trigger, 'run']);
        }
        return parent::behaviors();
    }

    /**
     * 设置事件
     *
     * @param $events
     *
     * @throws \yii\base\InvalidConfigException
     */
    public function setEvents($events)
    {
        // 检测 当前事件是否是 EventInterface 接口实现的
        foreach ($events as $event) {
            if (is_string($event)) {
                $event = [$event];
            }
            foreach ($event as $e) {
                $interfaces = class_implements($e);
                if (in_array(TriggerInterface::class, $interfaces)) {
                    $object = \Yii::createObject($e);
                    $eventName = call_user_func([$object, 'name']);
                    $this->on($eventName, [$object, 'run']);
                }
            }
        }
    }

    /**
     * 触发事件
     *
     * @param      $name
     * @param null $output 输出数据
     * @param null $input  输入原数据
     *
     * @return BaseEvent|null|Event
     */
    public function triggerServer($name, $output = null, $input = null)
    {
        if ($output instanceof Event) {
            $event = $output;
        } else {
            $event = new BaseEvent();
            $params = $output;
            if ($input !== null) {
                $params = [
                    'input'  => $input,
                    'output' => $output,
                ];
            }
            $event->params = $params;
        }
        parent::trigger($name, $event);
        return $event;
    }

    /**
     * 列表的数据转义
     *
     * @param array $data   数据
     * @param array $fields 转义字段
     * @param array $rule   规则 默认为字符串，['xx' => 'html']
     *
     * @return array
     * @author lengbin(lengbin0@gmail.com)
     */
    public function htmlSpecialChars(array $data, array $fields = [], array $rule = [])
    {
        if (empty($data) || empty($fields)) {
            return $data;
        }
        $new = [];
        $result = isset($data['models']) ? $data['models'] : $data;
        foreach ($result as $key => $dd) {
            $d = $dd;
            if (is_object($dd)) {
                $d = $dd->toArray();
            }
            $new[$key] = $d;
            foreach ($fields as $field) {
                if (!empty($rule[$field])) {
                    $isUnset = false;
                    $html = !empty($d[$field]) ? $d[$field] : null;
                    if ($rule[$field] instanceof \Closure) {
                        $html = call_user_func($rule[$field], $dd);
                    } else {
                        switch ($rule[$field]) {
                            case 'html':
                                $html = HtmlPurifier::process($html);
                                break;
                            case 'image':
                                $json = BaseHelper::isJson($d[$field]);
                                if (is_array($json)) {
                                    $d[$field] = $json['path'];
                                }
                                $html = !empty($d[$field]) ? BaseHelper::imageUrl($d[$field]) : '';
                                break;
                            case 'distance':
                                $html = NumberHelper::formatNumbers(($d[$field] / 1000), 1) . 'km';
                                break;
                            case 'date':
                                $html = BaseHelper::formatTime($d[$field]);
                                break;
                            case 'unset':
                                $isUnset = true;
                                break;
                            default:
                                $html = Html::encode($html);
                                break;
                        }
                    }
                    if ($isUnset) {
                        unset($new[$key][$field]);
                    } else {
                        $new[$key][$field] = $html;
                    }
                }
            }
        }
        if (isset($data['models'])) {
            $data['models'] = $new;
        } else {
            $data = $new;
        }
        return $data;
    }
}
